package multiThreading;

import java.util.HashMap;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import static java.lang.Thread.interrupted;
import static java.lang.Thread.sleep;

public class G implements Runnable {
    //Reentrantlock用法
    public static void main(String arg[]) {
        G g = new G();
        Thread g1 = new Thread(g);
        Thread g2 = new Thread(g);
        g1.setName("A");
        g2.setName("B");
        g1.start();
        g2.start();
        g2.interrupt();
    }

    @Override
    public void run() {
        ReentrantLock lock = new ReentrantLock();
        try {
//            sleep(100);
            lock.lockInterruptibly();//ReentrantLock中断锁的用途
            for (int i = 0; i < 100; i++) {
//                if(Thread.currentThread().getName().equals("B")){//如果当前线程的名字和B一样则返回
//                    Thread.currentThread().interrupted();
//                    return;
//                }
                System.out.println(Thread.currentThread().getName() + i);
            }
            lock.unlock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class g1 implements Runnable {
    //可轮询锁
    private static final ReentrantLock lock = new ReentrantLock();//要先定义一个全局变量锁

    public static void main(String arg[]) {
        g1 x = new g1();
        Thread x1 = new Thread(x);
        Thread x2 = new Thread(x);
        x1.setName("A");
        x2.setName("B");
        x1.start();
        x2.start();
//        x2.interrupt();
    }

    @Override
    public void run() {
//        if (lock.tryLock()) {//可轮询锁，结果就会只有一个锁的输出，当最先开始的线程获得锁的时候，之后开始的线程就会获得不了锁，所以不会输出
        try {
            if (lock.tryLock(1, TimeUnit.MILLISECONDS)) {//可轮询定时锁，在所规定的时间内，如果没有获得锁的话，就返回为false
                for (int i = 0; i < 100; i++) {
                    sleep(10);
                    System.out.println(Thread.currentThread().getName() + ":" + i);
                }
                lock.unlock();
            } else {
                System.out.println(Thread.currentThread().getName() + "未获得锁");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class g2 implements Runnable {
    private static final Semaphore s = new Semaphore(1);//开一个线程的数量，然后让三个线程同时开始的话，三个线程不会争抢，会一个一个顺序执行完毕

    public static void main(String arg[]) {
        g2 x = new g2();
        Thread x1 = new Thread(x);
        Thread x2 = new Thread(x);
        Thread x3 = new Thread(x);
        x1.setName("A");
        x2.setName("B");
        x3.setName("C");
        x1.start();
        x2.start();
        x3.start();
    }

    @Override
    public void run() {
        try {
            s.acquire();//当前线程获得锁
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
            s.release();//解开这个锁
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class g3 implements Runnable {
    private static final AtomicInteger atomic = new AtomicInteger(0);//将累加的结果初始化位0

    public static void main(String arg[]) {
        g3 x = new g3();
        Thread x1 = new Thread(x);
        Thread x2 = new Thread(x);
        x1.setName("A");
        x2.setName("B");
        x1.start();
        x2.start();
        try {
            sleep(1);//让主线程等待一下，防止结果重新更新
            System.out.println(g3.atomic.get());//当前对象的两个线程运行中所累加的结果
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        for (int i = 0; i < 260; i++) {
            atomic.getAndIncrement();//进行累加操作
        }
    }
}

class g4 implements Runnable {
    private static final Map<String, Object> map = new ConcurrentHashMap<>();
    private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public static void main(String arg[]) {
        g4 x = new g4();
        Thread x1 = new Thread(x);
        Thread x2 = new Thread(x);
        x1.setName("A");
        x2.setName("B");
        x1.start();
        x2.start();
    }

    public static void get() {
        lock.readLock().lock();//得到读锁
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + map.get(i + ""));
        }
        lock.readLock().unlock();//释放读锁
    }

    public static void write() {
        lock.writeLock().lock();//得到写锁
        for (int i = 0; i < 100; i++) {
            map.put(i + "", i + "");
        }
        lock.writeLock().unlock();//释放写锁
    }

    @Override
    public void run() {
        write();
        get();
    }
}


